var express = require('express');
var multer = require('multer');
var router = express.Router();
var fs = require('fs');
var path = require('path');
var mysql = require('mysql');

const upload = multer({ dest:'uploads/' })

const { exec } = require('child_process');

const http = require('http');
 


// 建立一个连接池
const db = mysql.createPool({
  host: "127.0.0.1", // mysql的默认端口号：3306
  user: "admin",
  password: "12345678",
  database: "gogogo", 
})

/**
 * 数组转树形结构
 * @param {array} list 被转换的数组
 * @param {number|string} root 根节点（最外层节点）的 id
 * @return array
 */
function arrayToTree(list, root) {
  const result = [] // 用于存放结果
  const map = {} // 用于存放 list 下的节点

  // 1. 遍历 list，将 list 下的所有节点以 id 作为索引存入 map
  for (const item of list) {
    map[item.id] = { ...item } // 浅拷贝
  }

  // 2. 再次遍历，将根节点放入最外层，子节点放入父节点
  for (const item of list) {
    // 3. 获取节点的 id 和 父 id
    const { id, parent_id } = item // ES6 解构赋值
    // 4. 如果是根节点，存入 result
    if (item.parent_id === root) {
      result.push(map[id])
    } else {
      // 5. 反之，存入到父节点
      map[parent_id].children
        ? map[parent_id].children.push(map[id])
        : (map[parent_id].children = [map[id]])
    }
  }
  // 将结果返回
  return result
}

/**
 * 重写数组Meta信息
 * @param {array}  要重写的数组
 * @param {array}  数组中meta需要包含且重写的属性
 * @return array
 */
function rewriteMeta(routes,metaArr) {
  routes.forEach(route=>{
    route['meta'] = {}
    metaArr.forEach(filed=>{
      if(route[filed]){
        route['meta'][filed] = route[filed]
      }
    })
  })
  return routes
}
 
// 分离人声和歌曲的函数
function separateVoiceAndSong(inputFile, outputVoice, outputSong) {
  // 使用ffmpeg命令分离人声和歌曲
  let execSql = `ffmpeg -i ${inputFile} -af pan="stereo|c0=c0|c1=-1*c1" -ac 1 ${outputSong}.mp3`
  exec(execSql, (error, stdout, stderr) => {
    if (error) {
      console.error(`出错代码: ${execSql}`);
      console.error(`执行出错: ${error}`);
      return;
    }
    console.log(`人声和歌曲分离成功，伴奏输出到: ${outputSong}.mp3`);
  });
}
 


/* GET home page. */
router.get('/gpt',  async (req, res, next) => {
  console.log('开始请求chatGPT...')
  const mykey = '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'
  const url = 'https://api.openai.com/v1/chat/completions?api_key=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';

  // 测试GPT————————————————————————————————————————————————————
  // 创建 OpenAI 客户端
  // const client = new OpenAI({
  //     apiKey: mykey,
  //     model: "gpt-3.5-turbo"
  // });
  
  // async function main() {
  //     // 创建完成请求
  //     const completion = await client.chat.completions.create({
  //         messages: [{ role: "system", content: "You are a helpful assistant." }]
  //     });
    
  //     console.log(completion.choices[0]);
  // }
  
  // main();
  const axios = require('axios');
  async function main() {
      try {
          const response = await axios.post(url, {
              messages: [{ role: "system", content: "You are a helpful assistant." }],
              model: "gpt-3.5-turbo"
          }, {
              headers: {
                  'Content-Type': 'application/json',
                  'Authorization': `Bearer ${mykey}`
              }
          });
          
          console.log(response.data.choices[0]);
      } catch (error) {
          console.error(error);
      }
  }
  main();
  // 测试GPT————————————————————————————————————————————————————
});

router.post('/test', upload.single('file'), function(req, res, next) {
  let file = req.file
  let time = new Date().getTime()
  let oldfilepath = path.join(__dirname,'../uploads',file.filename)
  let newfilepath = path.join(__dirname,'../uploads',time+'-'+file.originalname)
  let voicepath = path.join(__dirname,'../uploads',path.basename(time+'-'+file.originalname)+'-voice')
  let songpath = path.join(__dirname,'../uploads',path.basename(time+'-'+file.originalname)+'-song')
  fs.rename(oldfilepath,newfilepath,(err)=>{
    if(err) throw err;
    fs.stat(newfilepath,(err,stats)=>{
      if(err) throw err;
      console.log('文件保存成功,开始分离音频')
      // 调用函数进行分离，替换相应的文件路径
      separateVoiceAndSong(newfilepath, voicepath, songpath);
    })
  })
  let result = {
    code:200,
    data:{fileinfo:req.file,url:songpath+".mp3"},
    message:'上传成功'
  }
  res.json(result);
});

router.post('/testdownload', function(req, res) {
 res.download(req.body.filepath);
});

router.post('/getRoutes', function(req, res) {
  let routes = []
  db.query("select * from routes", (err, results) => {
    if (err) {
      console.log('路由数据库获取失败',err);
      res.status(201).json({
        code:201,
        data:routes,
        message:'路由数据库获取失败'
      })
    }else{
      let data = rewriteMeta(results,['title'])
      data = arrayToTree(data,0)
      routes = JSON.stringify(data)
      res.status(200).json({
        code:200,
        data:routes,
        message:'路由数据库获取成功'
      })
    }
  });
});

router.post('/getRoute', function(req, res) {
  let routes = []
  db.query("select * from routes where id = "+req.body.id, (err, results) => {
    if (err) {
      console.log('路由数据库获取失败',err);
      res.status(201).json({
        code:201,
        data:routes,
        message:'路由数据库获取失败'
      })
    }else{
      let data = rewriteMeta(results,['title'])
      routes = JSON.stringify(data)
      res.status(200).json({
        code:200,
        data:routes,
        message:'路由数据库获取成功'
      })
    }
  });
});

router.post('/deleteRoute', function(req, res) {
  db.query("delete from routes where id = " + req.body.id, (err, results) => {
    if (err) {
      console.log('路由数据库获取失败',err);
      res.status(201).json({
        code:201,
        data:JSON.stringify(err),
        message:'路由数据库删除失败'
      })
    }else{
      res.status(200).json({
        code:200,
        data:'ok',
        message:'路由数据库删除成功'
      })
    }
  });
});

router.post('/updateRoute', function(req, res) {
  let sql = `update routes set path = '${req.body.route.path}',name = '${req.body.route.name}',component = '${req.body.route.component}',redirect = '${req.body.route.redirect}',parent_id = ${req.body.route['parent_id']},title = '${req.body.route.title}',isshow = '${req.body.route.isshow}' where id = ${req.body.id}`
  db.query(sql, (err, results) => {
    if (err) {
      console.log('路由数据库获取失败',err);
      res.status(201).json({
        code:201,
        data:JSON.stringify(sql),
        message:'路由修改失败'
      })
    }else{
      res.status(200).json({
        code:200,
        data:JSON.stringify(req.body),
        message:'路由修改成功'
      })
    }
  });
});

router.post('/addRoute', function(req, res) {
  let route = req.body
  let sql = `insert into routes(path,name,component,redirect,parent_id,title) values('${route.path}','${route.name}','${route.component}','${route.redirect}',${route['parent_id']},'${route.title}')`;
  
  // 判断路由是否重复
  db.query("select * from routes", (err, results) => {
    if (err) {
      console.log('路由数据库获取失败',err);
      res.status(201).json({
        code:201,
        data:routes,
        message:'路由数据库获取失败'
      })
    }else{
      let data = rewriteMeta(results,['title'])
      let allow = true
      data.forEach(i=>{ if(i.name == route.name || i.path == route.path){ allow = false } })
      if(!allow){
        res.status(202).json({
          code:202,
          data:null,
          message:'路由重复插入，请更换名称及路径'
        })
      }else{
        // 开始插入路由
        db.query(sql, (err, results) => {
          if (err) {
            console.log('路由数据库插入失败',err);
            res.status(201).json({
              code:201,
              data:err,
              message:'路由数据库插入失败'
            })
          }else{
            console.log('插入成功')
            res.status(200).json({
              code:200,
              data:null,
              message:'路由数据库插入成功'
            })
          }
        });
      }
    }
  });
});

router.get('/text2speech', async function(req, res) {
  const textToSpeech  = require('@google-cloud/text-to-speech')
  const client = new textToSpeech.TextToSpeechClient();
  async function synthesizeText() {
      const text = '你好，世界!'
      const request = {
          input: { text },
          voice: { languageCode: 'zh-CN', ssmlGender: 'FEMALE' }, 
          audioconfig: { audioEncoding: 'MP3' },
      }
      const [response] = await client.synthesizeSpeech(request); 
      const audio = response.audioContent; 
      fs.writeFileSync('output.mp3', audio);
      console.log('audio:',audio)
  }

  synthesizeText();
});

module.exports = router;
